package net.lzzy.practicesapi1.aspects;

import net.lzzy.practicesapi1.constants.Messages;
import net.lzzy.practicesapi1.entities.User;
import net.lzzy.practicesapi1.services.UserService;
import net.lzzy.practicesapi1.utils.AspectUtil;
import net.lzzy.practicesapi1.utils.JwtUtil;
import net.lzzy.practicesapi1.web.models.ApiResult;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.UUID;


/**
 * @author locker
 */
@Component
@Aspect
public class CourseAspect {
    private final UserService service;

    @Autowired
    public CourseAspect(UserService service) {
        this.service = service;
    }

    @Pointcut("execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.getCourses(..)) || " +
            "execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.getOpenCourses(..)) || " +
            "execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.getPagedCourses(..)) || " +
            "execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.getPagedOpenCourses(..))")
    private void coursePoint(){}
    @Pointcut("execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.getTeachersCourses(..)) || " +
            "execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.add(..)) || " +
            "execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.update(..)) || " +
            "execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.openClose(..)) || " +
            "execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.delete(..))")
    private void teacherPoint(){}
    @Pointcut("execution(* net.lzzy.practicesapi1.web.courses.CourseApiController.getStudentsCourses(..))")
    private void studentPoint(){}

    @Around("coursePoint()")
    public ApiResult aroundCourseMethod(ProceedingJoinPoint point) throws Throwable {
        int[] allowRoles = new int[] {User.TYPE_TEACHER, User.TYPE_STUDENT};
        return check(point, allowRoles);
    }

    @Around("teacherPoint()")
    public ApiResult aroundTeacherMethod(ProceedingJoinPoint point) throws Throwable {
        int[] allowRoles = new int[] {User.TYPE_TEACHER};
        return check(point, allowRoles);
    }

    @Around("studentPoint()")
    public ApiResult aroundStudentMethod(ProceedingJoinPoint point) throws Throwable {
        int[] allowRoles = new int[] {User.TYPE_STUDENT};
        return check(point, allowRoles);
    }

    private ApiResult check(ProceedingJoinPoint point, int[] allowRoles) throws Throwable {
        String token = AspectUtil.getToken(point);
        String uid = JwtUtil.verifyToken(token);
        if (uid == null){
            return new ApiResult(false, "认证信息已失效，请重新登录", null);
        }
        User user = service.getUser(UUID.fromString(uid));
        if (user == null){
            return new ApiResult(false, Messages.WRONG_ID.toString(), null);
        }
        if (Arrays.stream(allowRoles).noneMatch(r -> r == user.getType())){
            return new ApiResult(false, Messages.NO_PERMISSION.toString(), null);
        }
        return (ApiResult) point.proceed();
    }
}
